(function ($) {
    'use strict';

    var SelectComp = function (el, options) {
        this.options = options;
        this.$el = $(el);
        this.init();
    };

    SelectComp.DEFAULTS = {
        dropdownEl: undefined,
        canFilter: true,
        outerEl: undefined,
        topEl: undefined
    };

    SelectComp.prototype = {
        init: function () {
            this.dropdownHidden();
            this.bindEvent();
        },

        dropdownHidden: function () {
            var options = this.options,
                dropdownEl = options.dropdownEl;
            if (dropdownEl === undefined) {
                throw new Error('dropdownEl Is undefined');
            }

            var $dropdownEl = $(dropdownEl);
            this.$dropdownEl = $dropdownEl;

            if (!$dropdownEl.hasClass('select-comp')) {
                $dropdownEl.addClass('select-comp');
            }
        },

        bindEvent: function () {
            var options = this.options,
                canFilter = options.canFilter;
            this.bindShowEvent();

            if (canFilter) {
                this.bindFilterEvent();
            }
        },

        bindShowEvent: function () {
            var self = this,
                $el = self.$el;
            //显示下选择项的显示
            $el.on('click', function () {
                $el.trigger('inputClick');
                self.show();
            });
        },

        bindFilterEvent: function () {
            var self = this,
                $el = self.$el;

            var flag = false;
            $el.on('compositionstart', function () {
                flag = true;
            });
            $el.on('compositionend', function () {
                flag = false;
                $(this).trigger('filterChange');
            });
            $el.on('input', function () {
                if (flag) {
                    return;
                }
                $(this).trigger('filterChange');
            });
        },

        show: function () {
            var $dropdownEl = this.$dropdownEl;
            if (!$dropdownEl) {
                return;
            }

            var $el = this.$el;
            var position = this.getDropdownPosition();

            $dropdownEl.css({
                top: position.top + 'px',
                left: position.left + 'px',
            });
            $dropdownEl.show();

            $(document).off('mouseup', this.closeDropdown);
            $(document).on('mouseup', {
                self: this
            }, this.closeDropdown);
            $el.trigger('showDropdown');
        },

        closeDropdown: function (e) {
            var $eTarget = $(e.target);
            if ($eTarget.closest('.select-comp').length !== 0) {
                return;
            }

            var self = e.data.self;
            self.hidden();
            $(document).off('mouseup', self.closeDropdown);
        },

        hidden: function () {
            var $dropdownEl = this.$dropdownEl;
            $dropdownEl.hide();
            this.$el.trigger('hiddenDropdown');
        },

        getDropdownPosition: function () {
            var $dropdownEl = this.$dropdownEl,
                $el = this.$el,
                options = this.options;
            var top = $el.position().top;
            var height = $el.outerHeight();
            var marginTop = $el[0].style.marginTop;
            marginTop = marginTop.substring(0, marginTop.indexOf('px'));
            marginTop = Number(marginTop);
            top += marginTop;

            var totalHeight;
            var outerEl = options.outerEl;
            if (outerEl === undefined) {
                totalHeight = Math.max(document.body.scrollHeight, window.innerHeight);
            } else {
                totalHeight = $(outerEl).height();
            }

            var topEl = options.topEl;
            var left = $el.position().left;
            if (topEl !== undefined) {
                var topElTop = $(topEl).position().top;
                top += topElTop;

                var topElLeft = $(topEl).position().left;
                left += topElLeft;
            }

            var dropHeight = $dropdownEl.outerHeight();
            if (top + height + dropHeight > totalHeight) {
                top = top - dropHeight;
            } else {
                top = top + height;
            }

            return {
                top: top,
                left: left
            };
        }
    };

    var allowedMethods = ['show', 'hidden', 'destroy'];

    $.fn.selectComp = function (option) {
        var value,
            args = Array.prototype.slice.call(arguments, 1);
        this.each(function () {
            var $this = $(this),
                data = $this.data('select.comp'),
                options = $.extend({}, SelectComp.DEFAULTS, $this.data(),
                    typeof option === 'object' && option);
            if (typeof option === 'string') {
                if ($.inArray(option, allowedMethods) < 0) {
                    throw new Error("Unknown method: " + option);
                }

                if (!data) {
                    return;
                }

                value = data[option].apply(data, args);

                if (option === 'destroy') {
                    $this.removeData('select.comp');
                }
            }

            if (!data) {
                $this.data('select.comp', (data = new SelectComp(this, options)));
            }
        });
        return typeof value === 'undefined' ? this : value;
    };

    $.fn.selectComp.Constructor = SelectComp;
    $.fn.selectComp.defaults = SelectComp.DEFAULTS;
    $.fn.selectComp.methods = allowedMethods;
})(jQuery)